#============================================
# #知识点
# Socket是应用层与TCP/IP协议族通信的中间软件抽象层，它是一组接口。在设计模式中，Socket其实就是一个门面模式，
# 它把复杂的TCP/IP协议族隐藏在Socket接口后面，对用户来说，一组简单的接口就是全部，让Socket去组织数据，
# 以符合指定的协议。所以，我们无需深入理解tcp/udp协议，socket已经为我们封装好了
# ，我们只需要遵循socket的规定去编程，写出的程序自然就是遵循tcp/udp标准的。
# 也有人将socket说成ip+port，ip是用来标识互联网中的一台主机的位置，
# 而port是用来标识这台机器上的一个应用程序，ip地址是配置到网卡上的，
# 而port是应用程序开启的，ip与port的绑定就标识了互联网中独一无二的一个应用程序
# 而程序的pid是同一台机器上不同进程或者线程的标识
# 套接字家族的名字：AF_UNIX
# 套接字家族的名字：AF_INET
#============================================
import socket
#注意这里的发数据和收数据，都是在自己的内存中去收发(缓存有一定大小)
#服务端
obj = socket.socket("链接类型","链接方式")   #返回一个对象(服务端)
# socket.AF_INET 网络连接; socket.SOCK_STREAM tcp协议, socket.SOCK_DGRAM udp协议;
obj.bind(("ip","port")) #绑定ip与端口
obj.listen(5)   #开启这个端 ，5为半链接池数量
while True:   #链接循环(不建议和通信循环一起用)
    coon,ip_port = obj.accept()   #等待电话连接，接受到返回数据为元组，分别存放 连接对象 和 ip地址加端口
    while True:   #通信循环
        try:                     #针对windons系统
            data = coon.recv(1024)  #接收消息
            if len(data) == 0:   #如果服务端收到信息为空，说明出问题，应该终止掉循环，结束链接
                break             #针对uinx系统
            print(data.decode("utf-8"))  #查看接受的消息
            coon.send(data.upper())   #发送消息
        except:
            break
    break  #方便观看没用（删除）
    coon.close()  #关闭连接coon
obj.close()   #关闭端（可有可无）

#客户端
obj = socket.socket("链接类型","链接方式")   #返回一个对象(客户端)
obj.connect(("ip","port"))  #与服务器建立连接（服务端的ip与地址）
while True:   #通信循环
    msg = input("输入一段话通信")
    if len(msg) == 0:  #防止输入空信息，服务端收不到信息而卡顿
        continue 
    # if msg == "q":
    #     break
    obj.send(msg.encode("utf-8"))   #建立连接，就可以以自己多为对象来发送数据
    data = obj.recv()  #接受数据
    print(data.decode("utf-8"))  #查看接受的消息
    break #方便观看没用（删除）
obj.close()  #关闭客户端
#============================================
# 基于udp通信
# udp协议中没有建立链接之说，直接收接数据
#服务端
sever = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
obj.bind(("ip","port")) #绑定ip与端口
data,ip_port = obj.recvfrom()
print(data.decode("utf-8"))
obj.sendto(data.encode("utf-8"),ip_port)
sever.close()

#客户端
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
obj.sendto(data.encode("utf-8"),("ip","port"))
data,ip_port = obj.recvfrom()
print(data.decode("utf-8"))
sever.close()
#============================================
# tcp列子
#服务端
import socket
obj = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
obj.bind(("127.0.0.1",8888))
obj.listen(5)
conn,ip_port = obj.accept()
print(ip_port)
while True:
    try:
        data = conn.recv(1024)
        if len(data) ==0:    
            break
        print(data.decode("utf-8"))
        conn.send(data.upper())
    except:
        break
conn.close()

#客户端
import socket
obj = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
obj.connect(("127.0.0.1",8888))
while True:
    msg = input("输入一段话:")
    if len(msg) == 0:
        continue
##    if msg == "q":
##        break
    obj.send(msg.encode("utf-8"))
    data = obj.recv(1024)
    print(data.decode("utf-8"))
obj.close()
#============================================
